package com.zzq.service.impl;


import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.zzq.domain.dto.SmilePhotographerDTO;
import com.zzq.domain.dto.SmilePhotographerKpiDTO;
import com.zzq.domain.dto.SmilePhotographerWithdrawalRecordDTO;
import com.zzq.domain.entity.*;
import com.zzq.domain.search.PhotographerSearchParamet;
import com.zzq.domain.search.PhotographerWithdrawalRecordSearchParamet;
import com.zzq.enumerate.*;
import com.zzq.result.SmileResult;
import com.zzq.security.PhotographerSecurityDTO;
import com.zzq.security.ex.AuditAuthenticationException;
import com.zzq.security.ex.NoUserAuthenticationException;
import com.zzq.security.util.UserUtil;
import com.zzq.service.*;
import com.zzq.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.zzq.enumerate.RedisKeyEnum.SMILE_PHOTOGRAPHER_LOGIN;

@Service
public class PhotographerSericeImpl implements PhotographerService {

    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.appsecret}")
    private String appsecret;

    @Value("${wx.login.url}")
    private String loginUrl;



    @Autowired
    SmilePhotographerService photographerService;
    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    SmilePhotographerDividendServiceImpl photographerDividendService;

    @Autowired
    SmilePhotographerReferralService photographerReferralService;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    SmilePhotographerDividendRuleService photographerDividendRuleService;

    @Autowired
    SmileProductRecordService productRecordService;

    @Autowired
    SmilePhotographerWithdrawalRecordService photographerWithdrawalRecordService;

    @Autowired
    SmilePhotographerDividendBillService photographerDividendBillService;

    @Autowired
    RedisCache redisCache;

    @Autowired
    OssFileUtil ossFileUtil;

    @Override
    public SmileResult photographerLogin(SmilePhotographer photographer) {
        //获取认证信息

        Authentication authenticate = null;
        try {
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(photographer.getPhotographerAccount(), photographer.getPhotographerPassword());
            authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        } catch (AuthenticationException exception) {
            if (exception instanceof BadCredentialsException) {
                return SmileResult.waring("账号或者密码错误");
            } else if (exception instanceof DisabledException) {
                return SmileResult.waring("用户被禁用");
            } else if (exception instanceof LockedException) {
                return SmileResult.waring("用户被锁定");
            } else if (exception instanceof AccountExpiredException) {
                return SmileResult.waring("用户已过期");
            } else if (exception instanceof NoUserAuthenticationException) {
                return SmileResult.waring("用户不存在");
            } else if (exception instanceof AuditAuthenticationException) {
                return SmileResult.waring("用户未审核");
            } else {
                return SmileResult.waring("认证失败");
            }
        }

        if (Objects.isNull(authenticate)) {
//            throw new ShopException("登录失败");
            return SmileResult.waring("账号或者密码错误");
        }
        //获取id生成jwt
        SmilePhotographer user = ((PhotographerSecurityDTO) authenticate.getPrincipal()).getUser();
        String id = user.getId().toString();
        String token = JwtUtil.createJWT(id);
        //将jwt用map存储放入redis
        //过期时间两个小时
        redisCache.setCacheObject(SMILE_PHOTOGRAPHER_LOGIN.key(id), user,7200);

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("user", user);
        return new SmileResult(200, "登陆成功", map);
    }

    @Override
    public SmileResult photographerLoginOut() {
        Long userID = UserUtil.getUserID();
        redisCache.deleteObject(SMILE_PHOTOGRAPHER_LOGIN.key(userID));
        return SmileResult.sucess("登出成功");
    }

    @Override
    @Transactional
    public SmileResult photographerRegister(String code,SmilePhotographer photographer) {


//        if (Objects.isNull(photographer.getPhotographerPhone())) {
//            return new SmileResult(300, "手机号不能为空");
//        }
//        if (Objects.isNull(photographer.getPhotographerIdCard())) {
//            return new SmileResult(300, "身份证不能空");
//        }
//        if (Objects.isNull(photographer.getPhotographerPassword())) {
//            return new SmileResult(300, "密码不能空");
//        }
//        if (Objects.isNull(photographer.getPhotographerSeniority())) {
//            return new SmileResult(300, "工龄不能空");
//        }
        /*
        验证账号
         */
        String photographerPhone = photographer.getPhotographerPhone();
        LambdaQueryWrapper<SmilePhotographer> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SmilePhotographer::getPhotographerPhone, photographerPhone);
        int count = photographerService.count(wrapper);
        if (count > 0) {
            return SmileResult.waring("账号已存在");
        }
        /*
        获取openid
         */
        Map<String,Object> wxMap=new HashMap<>();
        wxMap.put("appid", appid);
        //小程序secret
        wxMap.put("secret", appsecret);
        //小程序端返回的code
        wxMap.put("js_code", code);
        wxMap.put("grant_type", "authorization_code");
        String openidRes = HttpUtil.createGet(loginUrl).form(wxMap).execute().body();
        JSONObject openidJson = JSON.parseObject(openidRes);
        String openId = openidJson.getString("openid");
        photographer.setOpenId(openId);
        /*
        保存摄影师
         */
        String encode = passwordEncoder.encode(photographer.getPhotographerPassword());
        photographer.setPhotographerPassword(encode);
        photographer.setPhotographerAccount(photographerPhone);
        photographer.setAudit(AuditEnum.UNAUDIT.getName());
        photographer.setReferralCode(UUIDUtil.generateCustomString(6));
        photographerService.save(photographer);

        /*
         存在推荐码的情况
          需要添加一个分佣分红，并且添加推荐关系
         */
        if (!ObjectUtils.isEmpty(photographer.getRegisterReferralCode())){
            String registerReferralCode = photographer.getRegisterReferralCode();
            SmilePhotographer referralPhotographer = photographerService.getPhotographerByRegisteReferralCode(registerReferralCode);
            Long referralPhotographerId = referralPhotographer.getId();
            //判断是否存在佣金分红
            Boolean emptyDividend = photographerDividendService.isEmptyDividend(referralPhotographerId, DividendTypeEnum.COMMISSION_DIVIDEND.getName(), true);
            if (!emptyDividend){

                SmilePhotographerDividend photographerDividend=new SmilePhotographerDividend();
                photographerDividend.setPhotographerId(referralPhotographerId);
                photographerDividend.setPhotographerDividendType(DividendTypeEnum.COMMISSION_DIVIDEND.getName());
                photographerDividend.setPhotographerDividendProportionLock(true);
                SmilePhotographerDividendRule commissionRule = photographerDividendRuleService.getCommissionRule();
                BigDecimal photographerDividendProportion = commissionRule.getPhotographerDividendProportion();
                photographerDividend.setPhotographerDividendProportion(photographerDividendProportion);
                photographerDividendService.save(photographerDividend);

            }


            SmilePhotographerReferral smilePhotographerReferral = new SmilePhotographerReferral();
            smilePhotographerReferral.setPhotographerId(photographer.getId());
            smilePhotographerReferral.setReferralPhotographerId(referralPhotographerId);
            photographerReferralService.save(smilePhotographerReferral);
        }

        /*
         默认添加一个自己定义拍摄分红,但是不启用。
         */
        SmilePhotographerDividend photographerDividend=new SmilePhotographerDividend();
        photographerDividend.setPhotographerId(photographer.getId());
        photographerDividend.setPhotographerDividendType(DividendTypeEnum.SHOOT_DIVIDEND.getName());
        photographerDividend.setPhotographerDividendProportionLock(false);

        return SmileResult.sucess("注册成功");
    }

    @Override
    @Transactional
    public SmileResult setAvatar(MultipartFile file) {
        Long userID = UserUtil.getUserID();
        try {
            String fileName = ossFileUtil.uploadStaticFile(file, OssPathEnum.PHOTOGRAPHER_AVATAR.getPath(), userID+"" );
            String avatarUrl = ossFileUtil.getStaticFileUrl(fileName);
            LambdaUpdateWrapper<SmilePhotographer> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(SmilePhotographer::getId, userID);
            wrapper.set(SmilePhotographer::getPhotographerAvatar, avatarUrl);
            photographerService.update(wrapper);
            return SmileResult.sucess("头像设置成功",avatarUrl);
        } catch (IOException e) {
            return SmileResult.error("文件上传失败");
        } catch (ClientException e) {
            return SmileResult.error("oss上传失败");
        }


    }

    @Override
    public SmileResult getPhotographerInfoById(Long photographerId) {
        PhotographerSearchParamet searchParamet=new PhotographerSearchParamet();
        searchParamet.setPhotographerId(photographerId);
        List<SmilePhotographerDTO> photographerDTOList = photographerService.getPhotographerDTOList(searchParamet);

        if (ObjectUtils.isListSole(photographerDTOList)){
            return   SmileResult.sucess("查询成功",photographerDTOList.get(0));
        }
        return SmileResult.waring("查无结果");
    }

    @Override
    public SmileResult getPhotographerKpiById(Long photographerId) {
        PhotographerSearchParamet searchParamet=new PhotographerSearchParamet();
        searchParamet.setPhotographerId(photographerId);
        List<SmilePhotographerKpiDTO> photographerKpiDTOList = photographerService.getPhotographerKpiDTOList(searchParamet);


        Map<String, SmilePhotographerKpiDTO> photographerKpiDTOMap =
                photographerKpiDTOList.stream()
                        .collect(Collectors.toMap(SmilePhotographerKpiDTO::getPhotographerDividendType,
                                photographerKpiDTO -> {
                                    if (photographerKpiDTO.getPhotographerDividendType().equals(DividendTypeEnum.SHOOT_DIVIDEND.getName())) {
                                        SmilePhotographerDividend myshootDividendRule = photographerDividendService.getShootDividendRule(photographerId);
                                        if (ObjectUtils.isEmpty(myshootDividendRule)){
                                            SmilePhotographerDividendRule shootDividendRule = photographerDividendRuleService.getShootRule(photographerKpiDTO.getShootAmount());
                                            photographerKpiDTO.setDividendProportion(shootDividendRule.getPhotographerDividendProportion());

                                        }else {
                                            photographerKpiDTO.setDividendProportion(myshootDividendRule.getPhotographerDividendProportion());
                                        }
                                    }
                                    return photographerKpiDTO;
                                }));
        return SmileResult.sucess("查询成功",photographerKpiDTOMap);
    }

    @Override
    @Transactional
    public SmileResult setPhotographerBank(SmilePhotographerDTO smilePhotographerDTO) {
        smilePhotographerDTO.getPhotographerId();
        SmilePhotographer smilePhotographer = BeanCopyUtils.copyBean(smilePhotographerDTO, SmilePhotographer.class);
        smilePhotographer.setId(smilePhotographerDTO.getPhotographerId());
        photographerService.updateById(smilePhotographer);
        return SmileResult.sucess("更新成功");
    }

    @Override
    @Transactional
    public SmileResult withdraw(Long photographerId) {
        LambdaQueryWrapper<SmilePhotographerWithdrawalRecord> recordLambdaQueryWrapper=new LambdaQueryWrapper<>();
        recordLambdaQueryWrapper.orderByDesc(SmilePhotographerWithdrawalRecord::getCreatedTime);
        recordLambdaQueryWrapper.eq(SmilePhotographerWithdrawalRecord::getPhotographerId,photographerId);
        List<SmilePhotographerWithdrawalRecord> lastWithdrawalRecords = photographerWithdrawalRecordService.list(recordLambdaQueryWrapper);
        SmilePhotographerWithdrawalRecord lastwithdrawalRecord;
        if (!ObjectUtils.isEmpty(lastWithdrawalRecords)){
            lastwithdrawalRecord= lastWithdrawalRecords.stream().findFirst().get();
            Date baseTime = lastwithdrawalRecord.getCreatedTime();
            int i = CommonUtils.remainingDays(baseTime, new Date(), 7);
            if (i>0) {
                return SmileResult.waring("提现失败,提现冷却未结束",i);
            }
        }
        List<SmilePhotographerDividendBill> billList = photographerDividendBillService.getBillListByPhotographerId(photographerId, false);

        BigDecimal dividendAmount = billList.stream().map(SmilePhotographerDividendBill::getPhotographerDividendAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        SmilePhotographerWithdrawalRecord withdrawalRecord=new SmilePhotographerWithdrawalRecord();
        withdrawalRecord.setPhotographerId(photographerId);
        withdrawalRecord.setWithdrawalAmount(dividendAmount);
        withdrawalRecord.setAudit(AuditEnum.AUDITING.getName());
        withdrawalRecord.setWithdrawalStatus(WithdrawalStatusEnum.NO_WITHDRAWAL.getName());
        boolean save = photographerWithdrawalRecordService.save(withdrawalRecord);


        return SmileResult.sucess("已提交申请",dividendAmount);
    }

    @Override
    public SmileResult getWithdrawRecordById(Long photographerId) {
        PhotographerWithdrawalRecordSearchParamet searchParamet=new PhotographerWithdrawalRecordSearchParamet();
        searchParamet.setPhotographerId(photographerId);
        List<SmilePhotographerWithdrawalRecordDTO> withdrawalRecordDTOList = photographerWithdrawalRecordService.getWithdrawalRecordDTO(searchParamet);
        if (!ObjectUtils.isEmpty(withdrawalRecordDTOList)) {
            return SmileResult.sucess("成功",withdrawalRecordDTOList);
        }
        return SmileResult.waring("查无记录");
    }

}
